﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;

namespace LeslieXin.SimpleMVVM
{
    /* Author: Leslie Xin
     * E-Mail: lesliexin@outlook.com
     * WebSite: http://www.lesliexin.com
     * Datetime: 2025-05-11
     * 
     * V3
     */

    /// <summary>
    /// LeslieXin.SimpleMVVM
    /// </summary>
    public class SimpleMVVM
    {
        /// <summary>
        /// ViewModel基础类
        /// </summary>
        public abstract class ViewModelBase : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
            /// <summary>
            /// 确认属性变更，不用输入属性名
            /// </summary>
            /// <param name="propertyName"></param>
            protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
            /// <summary>
            /// 确认属性变更，不用输入属性名（仿照官方用法）
            /// </summary>
            /// <param name="prop"></param>
            /// <param name="value"></param>
            /// <param name="propertyName"></param>
            protected virtual void SetProperty<T>(ref T prop, T value, [CallerMemberName] string propertyName = null)
            {
                prop = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        /// <summary>
        /// Command基础类
        /// </summary>
        public class RelayCommand<T> : ICommand
        {
            public event EventHandler CanExecuteChanged
            {
                add
                {
                    if (_canExecute != null)
                    {
                        CommandManager.RequerySuggested += value;
                    }
                }
                remove
                {
                    if (_canExecute != null)
                    {
                        CommandManager.RequerySuggested -= value;
                    }
                }
            }

            public bool CanExecute(object parameter)
            {
                if (_canExecute == null)
                {
                    return true;
                }
                if (parameter is T x)
                {
                    return _canExecute(x);
                }
                else
                {
                    return false;
                }
            }

            public void Execute(object parameter)
            {
                if (_execute != null && CanExecute(parameter))
                {
                    if (parameter is T x)
                    {
                        _execute(x);
                    }
                }
            }

            private Func<T, bool> _canExecute;
            private Action<T> _execute;

            /// <summary>
            /// 【只需要实例化此类，不用调用此类中的方法】实例化命令类
            /// </summary>
            /// <param name="execute"></param>
            /// <param name="canExecute"></param>
            public RelayCommand(Action<T> execute, Func<T, bool> canExecute)
            {
                _execute = execute;
                _canExecute = canExecute;
            }
            /// <summary>
            /// 【只需要实例化此类，不用调用此类中的方法】实例化命令类，这种情况默认即是可执行的
            /// </summary>
            /// <param name="execute"></param>
            public RelayCommand(Action<T> execute) :
                this(execute, null)
            {
            }
        }
        
        /// <summary>
        /// Command基础类(无需参数)
        /// </summary>
        public class RelayCommand : ICommand
        {
            public event EventHandler CanExecuteChanged
            {
                add
                {
                    if (_canExecute != null)
                    {
                        CommandManager.RequerySuggested += value;
                    }
                }
                remove
                {
                    if (_canExecute != null)
                    {
                        CommandManager.RequerySuggested -= value;
                    }
                }
            }

            public bool CanExecute(object parameter)
            {
                if (_canExecute == null)
                {
                    return true;
                }
                return _canExecute();
            }

            public void Execute(object parameter)
            {
                if (_execute != null && CanExecute(parameter))
                {
                    _execute();
                }
            }

            private Func<bool> _canExecute;
            private Action _execute;

            /// <summary>
            /// 【只需要实例化此类，不用调用此类中的方法】实例化命令类
            /// </summary>
            /// <param name="execute"></param>
            /// <param name="canExecute"></param>
            public RelayCommand(Action execute, Func<bool> canExecute)
            {
                _execute = execute;
                _canExecute = canExecute;
            }
            /// <summary>
            /// 【只需要实例化此类，不用调用此类中的方法】实例化命令类，这种情况默认即是可执行的
            /// </summary>
            /// <param name="execute"></param>
            public RelayCommand(Action execute) :
                this(execute, null)
            {
            }
        }


        /// <summary>
        /// 事件聚合器
        /// </summary>
        internal class EventAggregator
        {
            private readonly Dictionary<Type, List<Delegate>> _eventSubscribers = new Dictionary<Type, List<Delegate>>();

            /// <summary>
            /// 发布事件
            /// </summary>
            /// <typeparam name="TEvent"></typeparam>
            /// <param name="eventMessage"></param>
            public void Publish<TEvent>(TEvent eventMessage)
            {
                if (_eventSubscribers.ContainsKey(typeof(TEvent)))
                {
                    foreach (var subscriber in _eventSubscribers[typeof(TEvent)])
                    {
                        subscriber.DynamicInvoke(eventMessage);
                    }
                }
            }

            /// <summary>
            /// 订阅事件
            /// </summary>
            /// <typeparam name="TEvent"></typeparam>
            /// <param name="eventHandler"></param>
            public void Subscribe<TEvent>(Action<TEvent> eventHandler)
            {
                if (!_eventSubscribers.ContainsKey(typeof(TEvent)))
                {
                    _eventSubscribers[typeof(TEvent)] = new List<Delegate>();
                }
                _eventSubscribers[typeof(TEvent)].Add(eventHandler);
            }

            /// <summary>
            /// 取消订阅事件
            /// </summary>
            /// <typeparam name="TEvent"></typeparam>
            /// <param name="eventHandler"></param>
            public void Unsubscribe<TEvent>(Action<TEvent> eventHandler)
            {
                if (_eventSubscribers.ContainsKey(typeof(TEvent)))
                {
                    _eventSubscribers[typeof(TEvent)].Remove(eventHandler);
                }
            }
        }

        /// <summary>
        /// 信使
        /// </summary>
        public class Messenger
        {
            private static EventAggregator _ea = new EventAggregator();
            /// <summary>
            /// 注册消息类型
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="dealMsg"></param>
            public static void Register<T>(Action<T> dealMsg)
            {
                _ea.Subscribe(dealMsg);
            }
            /// <summary>
            /// 取消注册消息类型
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="dealMsg"></param>
            public static void UnRegister<T>(Action<T> dealMsg)
            {
                _ea.Unsubscribe(dealMsg);
            }
            /// <summary>
            /// 发送此类型的消息
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="msg"></param>
            public static void Send<T>(T msg)
            {
                _ea.Publish(msg);
            }

        }

        /// <summary>
        /// 信使数据基类
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public class MessageValue<T>
        {
            /// <summary>
            /// 实例化
            /// </summary>
            /// <param name="value"></param>
            public MessageValue(T value)
            {
                Value = value;
            }
            /// <summary>
            /// 信使数据
            /// </summary>
            public T Value { get; private set; }
        }

        /// <summary>
        /// 信使-新
        /// </summary>
        public class MessengerNew
        {
            private static readonly Lazy<MessengerNew> _instance = new Lazy<MessengerNew>(() => new MessengerNew());
            /// <summary>
            /// 单例
            /// </summary>
            public static MessengerNew Default => _instance.Value;

            private readonly ConcurrentDictionary<Type, ConcurrentDictionary<WeakReference, MessageHandlerWrapper>> _subscribers =
                new ConcurrentDictionary<Type, ConcurrentDictionary<WeakReference, MessageHandlerWrapper>>();

            private readonly ConcurrentQueue<MessageQueueItem> _messageQueue = new ConcurrentQueue<MessageQueueItem>();
            private readonly object _queueLock = new object();
            private bool _isProcessingQueue;

            private MessengerNew() { }

            #region 订阅管理
            /// <summary>
            /// 订阅消息
            /// </summary>
            /// <typeparam name="TMessage"></typeparam>
            /// <param name="subscriber"></param>
            /// <param name="handler"></param>
            public void Subscribe<TMessage>(object subscriber, Action<TMessage> handler,Dispatcher dispatcher = null)
            {
                if (subscriber == null) throw new ArgumentNullException(nameof(subscriber));
                if (handler == null) throw new ArgumentNullException(nameof(handler));

                var messageType = typeof(TMessage);
                var weakRef = new WeakReference(subscriber);

                var handlerWrapper = new MessageHandlerWrapper<TMessage>(handler, dispatcher ?? GetSafeDispatcher(subscriber));

                _subscribers.AddOrUpdate(messageType,
                    _ => new ConcurrentDictionary<WeakReference, MessageHandlerWrapper>(),
                    (_, existingDict) =>
                    {
                // 检查是否已存在相同订阅者的相同消息类型
                var existingEntry = existingDict.Keys.FirstOrDefault(k => k.Target == subscriber);
                        if (existingEntry != null)
                        {
                    // 替换现有的处理程序
                    existingDict[existingEntry] = handlerWrapper;
                            return existingDict;
                        }
                        return existingDict;
                    });

                // 如果不存在则添加新订阅
                _subscribers[messageType].TryAdd(weakRef, handlerWrapper);

                // 清理无效引用
                CleanupSubscribers(messageType);
            }
            /// <summary>
            /// 取消订阅消息
            /// </summary>
            /// <typeparam name="TMessage"></typeparam>
            /// <param name="subscriber"></param>
            public void Unsubscribe<TMessage>(object subscriber)
            {
                if (subscriber == null) throw new ArgumentNullException(nameof(subscriber));

                var messageType = typeof(TMessage);
                if (_subscribers.TryGetValue(messageType, out var subscribers))
                {
                    var entry = subscribers.Keys.FirstOrDefault(k => k.Target == subscriber);
                    if (entry != null)
                    {
                        subscribers.TryRemove(entry, out _);
                    }
                }
            }
            /// <summary>
            /// 取消订单所有消息
            /// </summary>
            /// <param name="subscriber"></param>
            public void UnsubscribeAll(object subscriber)
            {
                if (subscriber == null) throw new ArgumentNullException(nameof(subscriber));

                foreach (var messageType in _subscribers.Keys)
                {
                    if (_subscribers.TryGetValue(messageType, out var subscribers))
                    {
                        var entry = subscribers.Keys.FirstOrDefault(k => k.Target == subscriber);
                        if (entry != null)
                        {
                            subscribers.TryRemove(entry, out _);
                        }
                    }
                }
            }

            private void CleanupSubscribers(Type messageType)
            {
                if (_subscribers.TryGetValue(messageType, out var subscribers))
                {
                    var deadRefs = subscribers.Keys.Where(k => !k.IsAlive).ToList();
                    foreach (var deadRef in deadRefs)
                    {
                        subscribers.TryRemove(deadRef, out _);
                    }
                }
            }

            #endregion

            #region 消息发布
            /// <summary>
            /// 发布消息
            /// </summary>
            /// <typeparam name="TMessage"></typeparam>
            /// <param name="message"></param>
            public void Publish<TMessage>(TMessage message)
            {
                if (message == null) throw new ArgumentNullException(nameof(message));

                var messageType = typeof(TMessage);
                _messageQueue.Enqueue(new MessageQueueItem(messageType, message));

                lock (_queueLock)
                {
                    if (!_isProcessingQueue)
                    {
                        _isProcessingQueue = true;
                        ThreadPool.QueueUserWorkItem(_ => ProcessMessageQueue());
                    }
                }
            }

            private void ProcessMessageQueue()
            {
                while (_messageQueue.TryDequeue(out var queueItem))
                {
                    if (_subscribers.TryGetValue(queueItem.MessageType, out var subscribers))
                    {
                        // 复制当前订阅者列表以避免处理过程中修改
                        var activeSubscribers = subscribers
                            .Where(kv => kv.Key.IsAlive)
                            .ToList();

                        foreach (var subscriber in activeSubscribers)
                        {
                            var weakRef = subscriber.Key;
                            var handlerWrapper = subscriber.Value;

                            if (weakRef.IsAlive)
                            {
                                handlerWrapper.Invoke(queueItem.Message);
                            }
                            else
                            {
                                subscribers.TryRemove(weakRef, out _);
                            }
                        }
                    }
                }

                lock (_queueLock)
                {
                    if (_messageQueue.IsEmpty)
                    {
                        _isProcessingQueue = false;
                    }
                    else
                    {
                        ThreadPool.QueueUserWorkItem(_ => ProcessMessageQueue());
                    }
                }
            }

            #endregion

            #region 辅助类和方法

            private abstract class MessageHandlerWrapper
            {
                public abstract void Invoke(object message);
            }

            private class MessageHandlerWrapper<TMessage> : MessageHandlerWrapper
            {
                private readonly Action<TMessage> _handler;
                private readonly Dispatcher _dispatcher;

                public MessageHandlerWrapper(Action<TMessage> handler, Dispatcher dispatcher)
                {
                    _handler = handler;
                    _dispatcher = dispatcher;
                }

                public override void Invoke(object message)
                {
                    if (message is TMessage typedMessage)
                    {
                        if (_dispatcher != null && !_dispatcher.CheckAccess())
                        {
                            _dispatcher.Invoke(() => _handler(typedMessage));
                        }
                        else
                        {
                            _handler(typedMessage);
                        }
                    }
                }
            }

            private class MessageQueueItem
            {
                public Type MessageType { get; }
                public object Message { get; }

                public MessageQueueItem(Type messageType, object message)
                {
                    MessageType = messageType;
                    Message = message;
                }
            }

            private static Dispatcher GetSafeDispatcher(object subscriber)
            {
                try
                {
                    // 1. 显式指定的Dispatcher优先
                    if (subscriber is IRequireDispatcher dispatcherRequester)
                    {
                        return dispatcherRequester.Dispatcher;
                    }

                    // 2. 标准WPF UI元素
                    if (subscriber is DispatcherObject dispatcherObject)
                    {
                        return dispatcherObject.Dispatcher;
                    }

                    // 3. 检查Dispatcher属性
                    var property = subscriber.GetType().GetProperty("Dispatcher",
                        BindingFlags.Public | BindingFlags.Instance);
                    if (property != null && property.PropertyType == typeof(Dispatcher))
                    {
                        return (Dispatcher)property.GetValue(subscriber);
                    }

                    // 4. 使用当前应用程序的Dispatcher作为后备
                    if (Application.Current != null)
                    {
                        return Application.Current.Dispatcher;
                    }
                }
                catch
                {
                    // 忽略所有错误，返回null表示不需要Dispatcher
                }

                return null;
            }
            #endregion
        }

        /// <summary>
        /// 允许对象显式指定需要的Dispatcher
        /// </summary>
        public interface IRequireDispatcher
        {
            Dispatcher Dispatcher { get; }
        }
    }
}
